// Copyright (c) M5Stack. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef __M5_IMU_BASE_H__
#define __M5_IMU_BASE_H__

#include "../I2C_Class.hpp"

namespace m5
{
    class IMU_Base : public I2C_Device
    {
    public:
        enum imu_spec_t
        {
            imu_spec_none = 0,
            imu_spec_accel = 0b0001,
            imu_spec_gyro = 0b0010,
            imu_spec_mag = 0b0100,
        };

        struct point3d_i16_t
        {
            union
            {
                int16_t value[3];
                struct
                {
                    int16_t x;
                    int16_t y;
                    int16_t z;
                };
            } __attribute__((__packed__));
        };

        struct imu_raw_data_t
        {
            union
            {
                int16_t value[10] = {
                    0,
                };
                point3d_i16_t sensor[3];
                struct
                {
                    point3d_i16_t accel;
                    point3d_i16_t gyro;
                    point3d_i16_t mag;
                    int16_t temp;
                } __attribute__((__packed__));
            };
        };

        struct imu_convert_param_t
        {
            union
            {
                float value[3] = {8.0f / 32768.0f, 2000.0f / 32768.0f, 10.0f * 4912.0f / 32768.0f};
                struct
                {
                    float accel_res;
                    float gyro_res;
                    float mag_res;
                };
            };
            float temp_res = 1.0f;
            float temp_offset = 0.0f;
        };

        virtual ~IMU_Base();
        IMU_Base(std::uint8_t i2c_addr, std::uint32_t freq = 400000, I2C_Class* i2c = nullptr);
        virtual imu_spec_t begin(I2C_Class* i2c = nullptr) = 0;
        virtual imu_spec_t getImuRawData(imu_raw_data_t* data) const = 0;   //{ return (imu_spec_t)0; }
        virtual void getConvertParam(imu_convert_param_t* param) const = 0; //{}
        virtual bool getTempAdc(int16_t* adc) const { return false; };

        /*
            virtual bool getAccelAdc(std::int16_t* ax, std::int16_t* ay, std::int16_t* az) const { return false; }
            virtual bool getGyroAdc(std::int16_t* gx, std::int16_t* gy, std::int16_t* gz) const { return false; }
            virtual bool getAccel(float* ax, float* ay, float* az) const { return false; }
            virtual bool getGyro(float* gx, float* gy, float* gz) const { return false; }
            virtual bool getTemp(float *t) const { return false; };
        //*/

        virtual bool setINTPinActiveLogic(bool level) { return false; }
    };
} // namespace m5

#endif